$TITLE ('RTX-51 INITIALISATION')
$SYMBOLS
$NOXREF
$NOCOND
$NOMOD51
$NORB
$PAGELENGTH(80) PAGEWIDTH(110)
;************************************************************************
;*                                                                      *
;*    R T X - 5 1  :   INITIALISATION                                   *
;*                                                                      *
;*----------------------------------------------------------------------*
;*                                                                      *
;*    Filename     :   RTXINIT.A51                                      *
;*    Language     :   Keil A-51                                        *
;*    Dev. system  :   Keil uVision2                                    *
;*    Targetsystem :   Any system based upon 8051 up                    *
;*                                                                      *
;*    Purpose      :   Initialisation of all RTX-51 system variables    *
;*                     and tables.                                      *
;*                     System call os_start_system; Creation of the     *
;*                     first user task, leaves control to created task. *
;*                                                                      *
;*----------------------------------------------------------------------*
;* Rev. |  Released   | Programmer    | Comments                        *
;*----------------------------------------------------------------------*
;* 0.1  |   4.1.90    | E. Glatz      | Changes for V3.18               *
;* 0.2  |   8.3.91    | Th. Fischler  | Module/File RTX.A51 included    *
;*      |   5.4.91    |               | Changes for Version 4.0         *
;*      |  12.4.91    |               | os_start_system added           *
;*      |  17.4.91    |               | internal stack not cleared,     *
;*      |             |               | error checks added              *
;*      |   6.6.91    |               | user_num_table initialication   *
;*      |             |               | added                           *
;*      | 29.10.91    | Th. Fischler  | Identification string added     *
;*      | 13.04.92    |               | Initialization for bank-        *
;*      |             |               | switching added                 *
;* 5.0  | 10.10.94    | E. Glatz      | Mailbox init. changed           *
;*      | 13.10.94    |               | Mbx/sem init. changed           *
;* 5.10 | 19.04.96    |               | MOV R7,NOT_OK --> MOV R7,#NOT_OK*
;* 7.00 | 13.11.2001  | T. Mueller    | Release 7.00                    *
;************************************************************************
;*    Copyright 1991 .. 2001 METTLER  &  FUCHS  AG,  CH-8953 Dietikon   *
;************************************************************************

$INCLUDE (RTXDEBUG.INC)
$INCLUDE (RTXIMASK.INC)

;*----------------------------------------------------------------------*
;*      I M P O R T S
;*----------------------------------------------------------------------*

$INCLUDE (RTXCONST.INC)
$INCLUDE (RTXEXTRN.INC)

;       FROM RTXCREA
EXTRN   CODE (_os_create_task)

;       FROM RTXCLK
EXTRN   CODE (_os_set_slice)

;       FROM RTXDISP
EXTRN   CODE (?RTX_REDISPATCH)

;       FROM RTXCONF
EXTRN   CODE   (?RTX_INIT_INT_REG_FLAGS)
EXTRN   NUMBER (?RTX_CLK_INT_NBR)
EXTRN   NUMBER (?RTX_IE_INIT, ?RTX_IEN1_INIT, ?RTX_IEN2_INIT)
EXTRN   NUMBER (?RTX_BANKSWITCHING)
EXTRN   DATA   (?RTX_SAVE_INT_BANK)


;       FROM VERS
EXTRN   NUMBER  (?RTX_VERSION_PRE, ?RTX_VERSION_NBR)


;*----------------------------------------------------------------------*
;*      E X P O R T S
;*----------------------------------------------------------------------*

PUBLIC  _os_start_system


;*----------------------------------------------------------------------*
;*      C O N S T A N T S
;*----------------------------------------------------------------------*



?RTX?RTXINIT     SEGMENT CODE
                 RSEG    ?RTX?RTXINIT

;       Copyright String
;       ================
;
COPYRIGHT:     DB      'RTX-51'
               DB      ' (c) METTLER & FUCHS AG '

;       Version Identification
;       ======================
;
VERSION:       DB      ?RTX_VERSION_PRE
               DW      ?RTX_VERSION_NBR


;*----------------------------------------------------------------------*
;*      P R O C E D U R E S
;*----------------------------------------------------------------------*

;*----------------------------------------------------------------------*
;*      I N I T _ M B X
;*----------------------------------------------------------------------*
;*      Initialise mailbox control block.
;*      Assumes:        - mailbox control structure as follows:
;*                              MBX#_COUNT      DS  1
;*                              MBX#-TCOUNT     DS  1
;*                              MBX#_FIRST      DS  1  
;*                              MBX#_LAST       DS  1
;*                              MBX#_TFIRST     DS  1   
;*                              MBX#_TLAST      DS  1  
;*                              RESERVED        DS  2
;*
;*                      - FIFO layout as follows:
;*                              MBX#_NEFIFO     DS 16
;*                              MBX#_NFFIFO     DS 16
;*----------------------------------------------------------------------*
;*      Input:   - DPH --> MBX_PAGE
;*               - DPL --> MBX#_FIRST (start of mbx control block + 2)
;*               - ACC --> MBX#_FIFO (start of FIFO area)
;*
;*      Output:  - all mailbox FIFO first/last pointers initialised
;*               - DPH --> MBX_PAGE
;*               - DPL = DPL on entry + 20H (points to next control block)
;*               - ACC = ACC on entry + 8 (points to next FIFO area)
;*               - no other registers changed
;*----------------------------------------------------------------------*

?RTX?INIT_MBX?RTXINIT  SEGMENT CODE
                       RSEG    ?RTX?INIT_MBX?RTXINIT

INIT_MBX:      MOVX  @DPTR, A                   ; MBX#_FIRST = .MBX#_FIFO
               INC   DPL
               ADD   A, #00FH
               MOVX  @DPTR, A                   ; MBX#_LAST = .MBX#_FIFO+0FH
               INC   DPL
               INC   A
               MOVX  @DPTR, A                   ; MBX#_TFIRST = .MBX#_FIFO+10H
               INC   DPL
               ADD   A, #00FH
               MOVX  @DPTR, A                   ; MBX#_TLAST = .MBX#_FIFO+1FH
               INC   A                          ; ACC = .MBX#_FIFO+20H
               XCH   A, DPL
               ADD   A, #5
               XCH   A, DPL                     ; DPL =  .MBX#_FIRST + 8
               RET                              ; DPH not changed


;*----------------------------------------------------------------------*
;*      I N I T _ S E M
;*----------------------------------------------------------------------*
;*      Initialise semaphore control block.
;*      Assumes:        - semaphore control structure as follows:
;*                              RESERVED        DS  6
;*                              SEM#_FIRST      DS  1  
;*                              SEM#_LAST       DS  1
;*
;*                      - FIFO layout as follows:
;*                              SEM#_FIFO       DS 16
;*----------------------------------------------------------------------*
;*      Input:   - DPH --> SEM_PAGE
;*               - DPL --> SEM#_FIRST (start of sema control block + 6)
;*               - ACC --> SEM#_FIFO (start of FIFO area)
;*
;*      Output:  - all semaphore FIFO first/last pointers initialised
;*               - DPH --> SEM_PAGE
;*               - DPL = DPL on entry + 10H (points to next control block)
;*               - ACC = ACC on entry + 8 (points to next FIFO area)
;*               - no other registers changed
;*----------------------------------------------------------------------*

?RTX?INIT_SEM?RTXINIT  SEGMENT CODE
                       RSEG    ?RTX?INIT_SEM?RTXINIT

INIT_SEM:      MOVX  @DPTR, A                   ; SEMx_FIRST = .SEM#_FIFO
               INC   DPL
               MOVX  @DPTR, A                   ; SEMx_LAST = .SEM#_FIFO
               ADD   A, #10H                    ; ACC = SEM#_FIFO + 10H
               XCH   A, DPL
               ADD   A, #7
               XCH   A, DPL                     ; DPL = DPL on entry + 8
               RET                              ; DPH not changed


;*----------------------------------------------------------------------*
;*      C L E A R _ B L O C K _ I N _ P A G E
;*----------------------------------------------------------------------*
;*      Clear Block in External RAM Page.  (max 256 Byte)
;*----------------------------------------------------------------------*
;*      Input:   - DPTR points to start of RAM_PAGE
;*               - B holds the number of bytes to clear
;*                 the value 0 means 256 bytes
;*
;*      Output:  - RAM page filled with zero
;*----------------------------------------------------------------------*

?RTX?CLEAR_BLOCK_IN_PAGE?RTXINIT  SEGMENT CODE
                          RSEG    ?RTX?CLEAR_BLOCK_IN_PAGE?RTXINIT

CLEAR_BLOCK_IN_PAGE:
               CLR   A
CLEARP:        MOVX  @DPTR, A
               INC   DPL
               DJNZ  B, CLEARP
               RET


;*----------------------------------------------------------------------*
;*      F I L L _ B L O C K
;*----------------------------------------------------------------------*
;*      Fills a block of external RAM with a specified value.
;*      NOTE: Complete block must be in same external RAM page
;*            Do not use for internal RAM !
;*----------------------------------------------------------------------*
;*      Input:   - DPTR --> starting address of block
;*               - ACC  --> fill value
;*               - B    --> block size (byte count)
;*
;*      Output:  - Block filled with specified value.
;*----------------------------------------------------------------------*

?RTX?FILL_BLOCK?RTXINIT  SEGMENT CODE
                         RSEG    ?RTX?FILL_BLOCK?RTXINIT

FILL_BLOCK:    MOVX  @DPTR, A
               INC   DPL
               DJNZ  B, FILL_BLOCK
               RET



;*----------------------------------------------------------------------*
;*      O S _ S T A R T _ S Y S T E M
;*----------------------------------------------------------------------*
;*      Initialises the system variables and starts the first user
;*      task.
;*----------------------------------------------------------------------*
;*      Input:   - R7 : Task-number of the first user task
;*      Output:  - R7 :  0  : OK
;*                      -1  : Error while starting the system
;*----------------------------------------------------------------------*

?RTX?_os_start_system?RTXINIT  SEGMENT CODE
                                  RSEG  ?RTX?_os_start_system?RTXINIT

_os_start_system:
               DBG_BUSY
               CALL  ?RTX_INIT_INT_REG_FLAGS    ; Initialize the int. enable
                                                ; register bits

               ; Set interrupt masks to disable all interrupts
               MOV   ?RTX_NM_IE, #0
               JNB   ?RTX_ENA_INT_REG1, IBIT_INIT_DONE
               MOV   ?RTX_NM_IE1, #0
               JNB   ?RTX_ENA_INT_REG2, IBIT_INIT_DONE
               MOV   ?RTX_NM_IE2, #0
IBIT_INIT_DONE:
               RTX_EXCLUDE_INT


;----------------------------------------------------------------
;  Clear the RTX system memory space
;----------------------------------------------------------------
;       Clear RTX bitaddressable byte segment (internal RAM)

CLEAR_MEM:     CLR   A
               MOV   R0, #?RTX_BIT_RELBYTE_BEG
CLRBITRELBY:   MOV   @R0, A
               INC   R0
               CJNE  R0, #?RTX_BIT_RELBYTE_END, CLRBITRELBY

;       Clear RTX relocateable byte segment (internal RAM)
               CLR   A
               MOV   R0, #?RTX_RELBYTE_BEG
CLRRELBY:      MOV   @R0, A
               INC   R0
               CJNE  R0, #?RTX_RELBYTE_END, CLRRELBY

;       Clear RTX bit variables
               CLR   ?RTX_REQ_REDISPATCH
               CLR   ?RTX_FULL_CONTEXT
               CLR   ?RTX_SYSCLK_ISR
               CLR   ?RTX_REENTRANTFLAG
               CLR   ?RTX_ROUND_ROBIN_REQ
               CLR   ?RTX_ROUND_ROBIN_OK
               CLR   ?RTX_TS_DELAY
               CLR   ?RTX_TS_REQ
               CLR   ?RTX_BANKSW
               CLR   ?RTX_MBX_SUPPORT
               CLR   ?RTX_SEM_SUPPORT

               MOV   ?RTX_TMP4, R7               ; Save the input parameter


;       Clear all external RAM pages belonging to RTX-51
               ; ?RTX_SYS_PAGE
               MOV   DPTR, #?RTX_SYS_PAGE        ; Start address
               MOV   A, #LOW(?RTX_SYS_PAGE_END)
               CLR   C
               SUBB  A, #LOW(?RTX_SYS_PAGE)
               MOV   B, A                        ; Block length
               CALL  CLEAR_BLOCK_IN_PAGE
               ; AUX_PAGE
               MOV   DPTR, #?RTX_AUX_PAGE
               MOV   A, #LOW(?RTX_AUX_PAGE_END)
               CLR   C
               SUBB  A, #LOW(?RTX_AUX_PAGE)
               MOV   B, A
               CALL  CLEAR_BLOCK_IN_PAGE

               MOV   A, #?RTX_MAILBOX_SUPPORT 
               JZ    MBXDONE                     ; ?RTX_MBX_SUPPORT=0 by default
               ; Set support flag
               SETB  ?RTX_MBX_SUPPORT
               ; MBX_PAGE
               ; NOTE: assumes MBX_PAGE is page-aligned !
               MOV   DPTR, #?RTX_MBX_PAGE
               MOV   B, #LOW(?RTX_MBX_PAGE_END)
               CALL  CLEAR_BLOCK_IN_PAGE
MBXDONE:
               MOV   A, #?RTX_SEMAPHORE_SUPPORT 
               JZ    SEMDONE                     ; ?RTX_SEM_SUPPORT=0 by default
               ; Set support flag
               SETB  ?RTX_SEM_SUPPORT
               ; SEM_PAGE
               ; NOTE: assumes SEM_PAGE is page-aligned !
               MOV   DPTR, #?RTX_SEM_PAGE
               MOV   B, #LOW(?RTX_SEM_PAGE_END)
               CALL  CLEAR_BLOCK_IN_PAGE
SEMDONE:


;----------------------------------------------------------------
;  Init the system tables
;----------------------------------------------------------------
;       Initialise ready list

RDY_INIT:      MOV   A, #LOW(?RTX_RDY_PRIO0)
               MOV   ?RTX_RDY_FIRST0, A
               MOV   ?RTX_RDY_LAST0, A
               MOV   A, #LOW(?RTX_RDY_PRIO1)
               MOV   ?RTX_RDY_FIRST1, A
               MOV   ?RTX_RDY_LAST1, A
               MOV   A, #LOW(?RTX_RDY_PRIO2)
               MOV   ?RTX_RDY_FIRST2, A
               MOV   ?RTX_RDY_LAST2, A
               MOV   A, #LOW(?RTX_RDY_PRIO3)
               MOV   ?RTX_RDY_FIRST3, A
               MOV   ?RTX_RDY_LAST3, A
               MOV   ?RTX_SAVE_INT_TID, #NIL_TID

;       Initialise mailbox control blocks in ext. RAM
;       Assumes: - array of mailbox control blocks (each of size 8 byte)
;                  (this array must be in-page)
;                - array of FIFO's                
;                  (this array must be page-aligned)
MBX_INIT:      MOV   DPTR, #(?RTX_MBX_CONTROL_BASE+2)   ; .MBX0_FIRST
               MOV   A, #LOW(?RTX_MBX_PAGE)             ; .MBX0_FIFO
               MOV   B, #8
MBXINI:        CALL  INIT_MBX
               DJNZ  B, MBXINI

;       Initialise semaphore control blocks in ext. RAM
;       Assumes: - array of semaphore control blocks (each of size 8 byte)
;                  (this array must be in-page)
;                - array of FIFO's                
;                  (this array must be page-aligned)
SEM_INIT:      MOV   DPTR, #(?RTX_MBX_CONTROL_BASE+6)   ; .SEM0_FIRST
               MOV   A, #LOW(?RTX_SEM_PAGE)             ; .SEM0_FIFO
               MOV   B, #8
SEMINI:        CALL  INIT_SEM
               DJNZ  B, SEMINI

;       Initialise interrupt owner list in ext. RAM
;       --> list has to contain NIL_TID:
;
INT_LIST_INIT: MOV   B, #NBR_OF_INT             ; size of list
               MOV   A, #NIL_TID                ; fill value
               MOV   DPTR, #?RTX_INT_TID_TABLE_BASE  ; start address
               CALL  FILL_BLOCK
               ; Set the interrupt used by the system clock to SYSCLK_TID
               MOV   DPH, #HIGH(?RTX_INT_TID_TABLE_BASE)
               MOV   A, #LOW(?RTX_INT_TID_TABLE_BASE)
               ADD   A, #?RTX_CLK_INT_NBR       ; 8-bit addition possible
               MOV   DPL, A                     ; int-owner list is inpage
               MOV   A, #SYSCLK_TID
               MOVX  @DPTR, A

;       Initialise delay and interval list
;       (fill DELAY_LIST_CLK with 0FFH -> 'no entry')
;       (fill DELAY_LIST_TID with #NIL_TID)
;       (fill interval list with 0FFH -> 'no entry')
;
DEL_LIST_INIT: MOV   B, #TASK_COUNT             ; Size of list
               MOV   A, #0FFH                   ; Fill value
               MOV   DPTR, #?RTX_DELAY_LIST_CLK ; Start address
               CALL  FILL_BLOCK
               MOV   B, #TASK_COUNT             ; Size of list
               MOV   A, #0FFH                   ; Fill value
               MOV   DPTR, #?RTX_INTERVAL_LIST  ; Start address
               CALL  FILL_BLOCK
               MOV   B, #TASK_COUNT             ; Size of list
               MOV   A, #NIL_TID                ; Fill value
               MOV   DPTR, #?RTX_DELAY_LIST_TID ; Start address
               CALL  FILL_BLOCK

;       Initialise the TID-Table
;       TID_TABLE has to contain NIL_TID
;
TID_INIT:      MOV   B, #TASK_COUNT             ; Size of list
               MOV   A, #NIL_TID                ; Fill value
               MOV   DPTR, #?RTX_TID_TABLE      ; Start address
               CALL  FILL_BLOCK

;       Initialise the user_num_table in external RAM
;       --> list has to contain NO_TASK
;
USER_NUM_INIT: MOV   DPH, #HIGH(?RTX_USER_NUM_TABLE)
               MOV   DPL, #LOW(?RTX_USER_NUM_TABLE)
               MOV   B, #?RTX_MAXTASKN          ; user_num_table size-1
               INC   B                          ; number of bytes in table
               MOV   A, #NO_TASK                ; Fill table with NO_TASK
               CALL  FILL_BLOCK

;       Set the reentrant Flag-Bit
;
               MOV   A, #?RTX_REENTRANT
               JZ    BANK_INIT
               SETB  ?RTX_REENTRANTFLAG

;       Set the Code-Bank-Switch Flag-Bit
;
BANK_INIT:     MOV   A, #?RTX_BANKSWITCHING
               JZ    CLOCK_INIT
               SETB  ?RTX_BANKSW
               MOV   ?RTX_SAVE_INT_BANK, #0


;----------------------------------------------------------------
;  Init the system clock
;----------------------------------------------------------------
                ; Check if the user has defined an ISR with the
                ; same Interrupt-Vector as the system-clock
CLOCK_INIT:    MOV   DPTR, #?RTX_ISRDESCR
               MOV   A, #?RTX_CLK_INT_NBR
               MOVC  A, @A+DPTR
               JZ    CLOCK_OK
               ; An ISR occupies the system-clock interrupt
               MOV   R7, #NOT_OK                ; set return value
               RET

CLOCK_OK:      MOV   R6, #HIGH(DEFAULT_TIME_SLICE)
               MOV   R7, #LOW(DEFAULT_TIME_SLICE)
               CALL  _os_set_slice


;----------------------------------------------------------------
;  Create the first user task
;----------------------------------------------------------------
;       Create call will return because we have set highest priority
;       and processor=allocated.
FIRST_TASK:    SETB  ?RTX_PROCESSOR_ALLOCATED
               MOV   ?RTX_RUNNING_TID, #MAX_TID
               MOV   R7, ?RTX_TMP4
               CALL  _os_create_task
               ; Check the return value
               MOV   A, R7
               JZ    CREATE_OK
               ; the first task is not created
               MOV   R7, #NOT_OK                ; set return value
               RET
CREATE_OK:

;----------------------------------------------------------------
;  Set the interrupt enable masks and registers
;----------------------------------------------------------------
               ; Search the bit mask for the system-clock
SET_IE:        MOV   DPTR, #?RTX_INT_TO_BIT_TABLE_BASE
               MOV   A, #?RTX_CLK_INT_NBR
               MOV   B, #3                      ; 3 bytes/int-nbr in the table
               MUL   AB                         ; DPTR:ACC points to the
                                                ; system clock int. masks
               MOV   R0, A                      ; Save ACC
                ; Mask 0
               MOV   ?RTX_NM_IE, #?RTX_IE_INIT
               ORL   ?RTX_NM_IE, #080H           ; To be sure EA-bit is set
               MOV   ?RTX_D_IE, ?RTX_NM_IE
               MOV   ?RTX_ND_IE, ?RTX_NM_IE
               ; Set the system clock int-bit
               MOV   A, R0
               MOVC  A, @A+DPTR
               ORL   ?RTX_D_IE, A
               ORL   ?RTX_ND_IE, A
               MOV   ?RTX_IE, ?RTX_NM_IE
               JNB   ?RTX_ENA_INT_REG1, IMASK_DONE
               ; Mask 1
               MOV   ?RTX_NM_IE1, #?RTX_IEN1_INIT
               MOV   ?RTX_D_IE1, #?RTX_IEN1_INIT
               MOV   ?RTX_ND_IE1, #?RTX_IEN1_INIT
               ; Set the system clock int-bit
               INC   R0
               MOV   A, R0
               MOVC  A, @A+DPTR
               ORL   ?RTX_D_IE1, A
               ORL   ?RTX_ND_IE1, A
               MOV   ?RTX_IEN1, ?RTX_NM_IE1
               JNB   ?RTX_ENA_INT_REG2, IMASK_DONE
                ; Mask 2
               MOV   ?RTX_NM_IE2, #?RTX_IEN2_INIT
               MOV   ?RTX_D_IE2, #?RTX_IEN2_INIT
               MOV   ?RTX_ND_IE2, #?RTX_IEN2_INIT
               ; Set the system clock int-bit
               INC   R0
               MOV   A, R0
               MOVC  A, @A+DPTR
               ORL   ?RTX_D_IE2, A
               ORL   ?RTX_ND_IE2, A
               MOV   ?RTX_IEN2, ?RTX_NM_IE2

IMASK_DONE:
;       Now we are ready to start
               CLR   ?RTX_PROCESSOR_ALLOCATED        ; Release cpu for dispatch
               JMP   ?RTX_REDISPATCH                 ; Start dispatcher


;       END OF MODULE
;
        END
